#include "api_order_service.h"
#include "context.h"
#include "streamdata.h"
#include "log.h"
#include "9100_agency_api.pb.h"
#include "cache.h"
#include "Game.h"

static bool __init__ = ApiOrderService::Instance()->Init();

bool ApiOrderService::Init()
{
	(void)__init__;
    return true;
}


void ApiOrderService::OnApiOrderUpdate(api_order::ApiOrder& api_order)
{
    // 订单更新
    if (api_order.err_code() == agency_api::ErrorCode::Success)
    {
        api_order.set_state(api_order::ApiOrderState::API_ORDER_STATE_SUCCESS);
    }
    else if (api_order.err_code() == agency_api::ErrorCode::RespTimeout)
    {
        api_order.set_state(api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT);
    }
    else
    {
        api_order.set_state(api_order::ApiOrderState::API_ORDER_STATE_FAILED);
    }

	log_info("api_order:%s", api_order.ShortDebugString().c_str());

    // 更新 订单 后处理
    switch (api_order.op())
    {
    case api_order::API_ORDER_OP_BET_AND_WIN:
        OnBetAndWin(api_order);
        break;
    case api_order::API_ORDER_OP_BET:
        OnBet(api_order);
        break;
    case api_order::API_ORDER_OP_WIN:
        OnWin(api_order);
        break;
    case api_order::API_ORDER_OP_CANCLE_BET:
        OnCancleBet(api_order);
        break;
    case api_order::API_ORDER_OP_CANCLE_BET_AND_WIN:
        OnCancleBetAndWin(api_order);
        break;
    case api_order::API_ORDER_OP_REWARD:
        OnReward(api_order);
        break;
    default:
        break;
    }
}

void ApiOrderService::OnBetAndWin(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		{
			// 记录到 异常列表中
			PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除  
			// PushApiOrderFinish(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		default:
		break;
		} 
	} while (false);
}
void ApiOrderService::OnBet(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		{
			// 记录到 异常列表中
			// PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除 
			// PushApiOrderFinish(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		default:
		break;
		} 

	} while (false);
}
void ApiOrderService::OnWin(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		{
			// 记录到 异常列表中
			PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除 
			// PushApiOrderFinish(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		default:
		break;
		} 
	} while (false);
}
void ApiOrderService::OnCancleBet(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		{
			// 记录到 异常列表中
			PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除 
			// PushApiOrderFinish(api_order);
		}
		break;
		default:
		break;
		} 

	} while (false);
}

void ApiOrderService::OnCancleBetAndWin(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		{
			// 记录到 异常列表中
			PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除 
			// PushApiOrderFinish(api_order);
		}
		break;
		default:
		break;
		} 

	} while (false);
}

void ApiOrderService::OnReward(api_order::ApiOrder& api_order)
{
	do
	{
		switch (api_order.state())
		{
		case api_order::ApiOrderState::API_ORDER_STATE_TIMEOUT:
		case api_order::ApiOrderState::API_ORDER_STATE_FAILED:
		{
			// 记录到 异常列表中
			PushApiOrderCreate(api_order);
		}
		break;
		case api_order::ApiOrderState::API_ORDER_STATE_SUCCESS:
		{
			// 从 异常处理中 移除 
			// PushApiOrderFinish(api_order);
		}
		break;
		default:
		break;
		} 

	} while (false);
}

void ApiOrderService::PushApiOrderCreate(api_order::ApiOrder& api_order)
{
	api_order.set_act(api_order::API_ORDER_ACT_CREATE);
	unsigned int uid = api_order.uid();
	if (0 == uid)
	{
		log_error("wrong prarm,uid,%u", uid);
		return;
	}
	pushToMq(uid, api_order);

    // Ctx.host->MtSendtoSrv(api_order::API_ORDER_CMD_ORDER_EXCEPTION_CREATE_PUSH, SERVER_TYPE_API_ORDER_FOLLOW, &api_order, 0);
}
void ApiOrderService::PushApiOrderFinish(api_order::ApiOrder& api_order)
{
	api_order.set_act(api_order::API_ORDER_ACT_DELETE);
	unsigned int uid = api_order.uid();
	if (0 == uid)
	{
		log_error("wrong prarm,uid,%u", uid);
		return;
	}
	pushToMq(uid, api_order);
}

int ApiOrderService::pushToMq(const unsigned int uid, const api_order::ApiOrder& api_order)
{
	if (!Ctx.host->m_pGame->m_mqconn)
	{
		if (Ctx.host->m_pGame->initmq())
		{
			log_alert("mq reconnect OK");
		}
		else
		{
			log_error("mq reconnect fail");
		}
	}

	if (uid > 0)
	{
		string str;
		api_order.SerializeToString(&str);
		log_debug("procAssetFlowMQ,uid:%u,data len:%lu", uid, str.size());
		if (Ctx.host->m_pGame->m_mqconn)
		{
			amqp_basic_properties_t props;
			props._flags = AMQP_BASIC_DELIVERY_MODE_FLAG;
			props.delivery_mode = 2; /* persistent delivery mode */

			unsigned int index = uid % MOD_UID;
			amqp_bytes_t message;
			message.bytes = const_cast<char*>(str.data());
			message.len = str.size();
			int ret = amqp_basic_publish(Ctx.host->m_pGame->m_mqconn, Ctx.host->m_pGame->m_mqchannel, amqp_cstring_bytes(CGameServer::s_szexchange), amqp_cstring_bytes(std::to_string(index).c_str()), 0, 0, &props, message);
			log_debug("pushToMq,uid:%u,data len:%lu,ret:%x", uid, str.size(), ret);
			if (AMQP_STATUS_OK != ret)
			{
				log_error("amqp_basic_publish fail,ret:%d,msg len:%lu", ret, message.len);
				if (AMQP_STATUS_CONNECTION_CLOSED == ret || AMQP_STATUS_SOCKET_ERROR == ret)
				{
					Ctx.host->m_pGame->releasemq();
					if (Ctx.host->m_pGame->initmq())
					{
						ret = amqp_basic_publish(Ctx.host->m_pGame->m_mqconn, Ctx.host->m_pGame->m_mqchannel, amqp_cstring_bytes(CGameServer::s_szexchange), amqp_cstring_bytes(std::to_string(index).c_str()), 0, 0, &props, message);
						log_alert("mq reconnect OK, publish ret:%d", ret);
					}
					else
					{
						log_error("reconnect fail,ret:%d", ret);
						return 1;
					}
				}
			}
		}
	}
	return 0;
}

